#include <cstdlib>
#include <ctime>
#include <QTextStream>
#include <QVector>
#include "../../../include/Complex.h"
#include "../../../include/Operation.h"

QString cToS(const Complex&);
Complex randComplex();

int main(int argc, char* argv[])
{
    QTextStream console(stdout);
	console.setCodec("UTF-8");
	console << "~~~~~~~~~~~~~~~~~~~~~~~~~\n"
			<< "~~ Operation TESTBENCH ~~\n"
			<< "~~~~~~~~~~~~~~~~~~~~~~~~~\n";
    // Seed the random number generator
    srand(time(0));
    // Iterate through all available operations and 
    static const QVector<Operation>& op_list = *(Operation::operationList());
    QVector<Operation>::const_iterator it = op_list.begin();
    for ( ; it != op_list.end(); ++it) {
        OperationData::ArgumentList arg_list;
        Complex result;
        console << it->helpString() << '\n';
        for (uint i = 0; i < it->numArgs(); ++i){
            Complex rand_arg = randComplex();
            arg_list.append(rand_arg);
            console << QString("ARG %1 = %2\n").arg(i).arg(cToS(rand_arg));
        }
        try {
            result = it->call(arg_list);
            console << QString("RESULT = %1\n\n").arg(cToS(result));
        } catch (const Operation::Exception& e) {
            console << QString("ERROR:\n%1\n\n").arg(e.qWhat());
        }
    }

    return 0;
}

QString cToS(const Complex& c)
{
    return QString("(%1, %2)").arg(static_cast<double>(c.real())).
           arg(static_cast<double>(c.imag()));
}

Complex randComplex()
{
    Complex::RealType x = static_cast<Complex::RealType>(rand()) / RAND_MAX;
    Complex::RealType y = static_cast<Complex::RealType>(rand()) / RAND_MAX;
    return Complex(x, y);
}
